#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include "../Includes/Driver.h"
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

/// <summary>
/// Locals
/// </summary>
int fbdev = -1;

/// <summary>
/// TODO
/// </summary>
int FBDOpen(void)
{
	if ((fbdev = open("/dev/fb0", O_RDWR)) < 0)
		return -1;
	return 0;
}

/// <summary>
/// TODO
/// </summary>
int FBDCreateFramebuffer(FramebufferPtr fbo) {

	if (fbo == NULL)
		return -1;

	struct fb_fix_screeninfo fsi;   
	if (ioctl(fbdev, FBIOGET_FSCREENINFO, &fsi) < 0)
		return -1;

	struct fb_var_screeninfo vsi;   
	if (ioctl(fbdev, FBIOGET_VSCREENINFO, &vsi) < 0)
		return -1;

	fbo->top = 0;
	fbo->left = 0;
	fbo->width = vsi.xres;
	fbo->height = vsi.yres;
	fbo->stride = fsi.line_length;
	fbo->start = fsi.smem_start;
	fbo->len = fsi.smem_len;
	fbo->bpp = vsi.bits_per_pixel;
	fbo->state = 0;

	if ((fbo->base = mmap(NULL, fbo->len, PROT_READ | PROT_WRITE, MAP_SHARED, fbdev, 0)) == (void*)-1)
		return -1;

    fbo->base = fbo->base + fsi.smem_start % getpagesize();

	//memset(fbo->base, 100, 4000000);
	//printf("Base: %d (0x%x)\n", (int)fbo->base, (int)fbo->base);

	return 0;
}

/// <summary>
/// TODO
/// </summary>
int FBDCreateSurface(void) {
	return 0;
}

/// <summary>
/// TODO
/// </summary>
int FBDDestroySurface(SurfacePtr surface)
{
	if (surface == NULL)
		return -1;
	return 0;
}

/// <summary>
/// TODO
/// </summary>
int FBDClose(void) {
	
	if (fbdev < 0)
		return -1;
	close(fbdev);
	return 0;
}

/// <summary>
/// TODO
/// </summary>
int FBDInit(DriverPtr drv)
{
	if (drv == NULL)
		return -1;

	drv->state = 0;
	drv->name = "Generic FBDev";
	drv->Open = FBDOpen;
	drv->CreateSurface = FBDCreateSurface;
	drv->DestroySurface = FBDDestroySurface;
	drv->CreateFramebuffer = FBDCreateFramebuffer;
	drv->Close = FBDClose;

	return 0;
}
